home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / bin / ubiquity-dm < prev    next >
Text File  |  2009-09-11  |  11KB  |  275 lines

  1. #!/usr/bin/python
  2.  
  3. import os
  4. import sys
  5. import subprocess
  6. import time
  7. import signal
  8. import errno
  9. import imp
  10. import grp
  11.  
  12. sys.path.insert(0, '/usr/lib/ubiquity')
  13.  
  14. import ubiquity.frontend
  15. import pwd
  16.  
  17. from ubiquity import osextras
  18. from ubiquity.casper import get_casper
  19.  
  20. background = '/usr/share/backgrounds/warty-final-ubuntu.png'
  21.  
  22. class XStartupError(EnvironmentError):
  23.     pass
  24.  
  25. class MissingProgramError(EnvironmentError):
  26.     pass
  27.  
  28. class DM:
  29.     def __init__(self, vt, display, default_username):
  30.         self.vt = vt
  31.         self.display = display
  32.         self.server_started = False
  33.  
  34.         self.username = get_casper('USERNAME', default_username)
  35.         self.uid, self.gid = pwd.getpwnam(self.username)[2:4]
  36.         self.homedir = pwd.getpwnam(self.username)[5]
  37.         self.uid = int(self.uid)
  38.         self.gid = int(self.gid)
  39.         self.groups = []
  40.         for g in grp.getgrall():
  41.             if self.username in g[3] or g[0] == self.username:
  42.                 self.groups.append(g[2])
  43.  
  44.         # Look for a frontend module; we won't actually use it (yet), but
  45.         # this lets us find out which window manager etc. to launch. Be
  46.         # careful that importing this here will cause the underlying library
  47.         # to try to talk to the X server, which won't go well.
  48.         frontend_names = ['mythbuntu_ui', 'gtk_ui', 'kde_ui']
  49.         self.frontend = None
  50.         for f in frontend_names:
  51.             try:
  52.                 imp.find_module(f, ubiquity.frontend.__path__)
  53.                 self.frontend = f
  54.                 break
  55.             except ImportError:
  56.                 pass
  57.         else:
  58.             raise AttributeError, ('No frontend available; tried %s' %
  59.                                    ', '.join(frontend_names))
  60.  
  61.     def sigusr1_handler(self, signum, frame):
  62.         self.server_started = True
  63.  
  64.     def drop_privileges(self):
  65.         os.setgroups(self.groups)
  66.         os.setgid(self.gid)
  67.         os.setuid(self.uid)
  68.  
  69.     def server_preexec(self):
  70.         signal.signal(signal.SIGUSR1, signal.SIG_IGN)
  71.  
  72.     def run(self, *program):
  73.         null = open('/dev/null', 'w')
  74.         if not os.path.exists('/var/log/installer'):
  75.             os.makedirs('/var/log/installer')
  76.         logfile = open('/var/log/installer/dm', 'w')
  77.  
  78.         signal.signal(signal.SIGUSR1, self.sigusr1_handler)
  79.         signal.signal(signal.SIGTTIN, signal.SIG_IGN)
  80.         signal.signal(signal.SIGTTOU, signal.SIG_IGN)
  81.  
  82.         servercommand = ['X', '-br', '-ac', '-noreset', self.vt, self.display]
  83.         if self.frontend == 'mythbuntu_ui':
  84.             servercommand.append('-dpi')
  85.             servercommand.append('100')
  86.  
  87.         server = subprocess.Popen(servercommand, stdin=null, stdout=logfile, stderr=logfile, preexec_fn=self.server_preexec)
  88.  
  89.         os.environ['DISPLAY'] = self.display
  90.         os.environ['HOME'] = self.homedir
  91.  
  92.         # Really we should select on a pipe or something, but it's not worth
  93.         # the effort for now.
  94.         timeout = 60
  95.         while not self.server_started:
  96.             status = server.poll()
  97.             if type(status) is int and status != 0:
  98.                 raise XStartupError, "X server exited with return code " + str(status)
  99.             if timeout == 0:
  100.                 raise XStartupError, "X server failed to start after 60 seconds"
  101.             time.sleep(1)
  102.             timeout -= 1
  103.  
  104.         # Session bus, apparently needed by most interfaces now
  105.         if ('DBUS_SESSION_BUS_ADDRESS' not in os.environ and
  106.             osextras.find_on_path('dbus-launch')):
  107.             dbus_subp = subprocess.Popen(
  108.                 ['dbus-launch', '--exit-with-session'],
  109.                 stdin=null, stdout=subprocess.PIPE, stderr=logfile,
  110.                 preexec_fn=self.drop_privileges)
  111.             for line in dbus_subp.stdout:
  112.                 try:
  113.                     name, value = line.rstrip('\n').split('=', 1)
  114.                     os.environ[name] = value
  115.                 except ValueError:
  116.                     pass
  117.             dbus_subp.wait()
  118.  
  119.         gconfd_running = False
  120.         if ((self.frontend == 'gtk_ui' or self.frontend == 'mythbuntu_ui') and
  121.             osextras.find_on_path('gconftool-2')):
  122.             subprocess.call(['gconftool-2', '--spawn'],
  123.                             stdin=null, stdout=logfile, stderr=logfile,
  124.                             preexec_fn=self.drop_privileges)
  125.             gconfd_running = True
  126.  
  127.         extras = []
  128.         if self.frontend == 'gtk_ui' or self.frontend == 'mythbuntu_ui':
  129.             gconf_dir = ('xml:readwrite:%s' %
  130.                 os.path.expanduser('~%s/.gconf' %
  131.                 self.username))
  132.             accessibility = 'false'
  133.             if osextras.find_on_path('gconftool-2'):
  134.                 subprocess.call(
  135.                     ['gconftool-2', '--config-source', gconf_dir,
  136.                      '--type', 'int', '--set',
  137.                      '/apps/metacity/general/num_workspaces', '1'],
  138.                     stdin=null, stdout=logfile, stderr=logfile,
  139.                     preexec_fn=self.drop_privileges)
  140.                 subp = subprocess.Popen(
  141.                     ['gconftool-2', '--config-source', gconf_dir,
  142.                      '--get', '/desktop/gnome/interface/accessibility'],
  143.                     stdout=subprocess.PIPE, stderr=subprocess.PIPE,
  144.                     preexec_fn=self.drop_privileges)
  145.                 accessibility = subp.communicate()[0].rstrip('\n')
  146.             # Accessibility infrastructure
  147.             if accessibility == 'true':
  148.                 if os.path.exists('/usr/lib/at-spi/at-spi-registryd'):
  149.                     extras.append(subprocess.Popen(['/usr/lib/at-spi/at-spi-registryd'],
  150.                         stdin=null, stdout=logfile, stderr=logfile))
  151.                     os.environ['GTK_MODULES'] = 'gail:atk-bridge'
  152.  
  153.             maybe_drop_privileges = {}
  154.             if accessibility != 'true':
  155.                 maybe_drop_privileges['preexec_fn'] = self.drop_privileges
  156.  
  157.             # Don't show the background image in v1 accessibility profile. It
  158.             # is not shown in the GNOME desktop after all.
  159.             fp = open('/proc/cmdline', 'r')
  160.             if os.access(background, os.R_OK) and not 'access=v1' in fp.readline():
  161.                 import gtk
  162.                 pixbuf = gtk.gdk.pixbuf_new_from_file(background)
  163.                 root = gtk.gdk.get_default_root_window()
  164.                 (root_width, root_height) = root.get_size()
  165.                 scaled = pixbuf.scale_simple(root_width, root_height, gtk.gdk.INTERP_BILINEAR)
  166.                 (pixmap, mask) = scaled.render_pixmap_and_mask(0)
  167.                 root.set_back_pixmap(pixmap, False)
  168.                 root.clear()
  169.                 gtk.gdk.flush()
  170.             fp.close()
  171.  
  172.         if self.frontend in ('gtk_ui', 'mythbuntu_ui'):
  173.             if gconfd_running and osextras.find_on_path('metacity'):
  174.                 wm = subprocess.Popen(['metacity', '--sm-disable'],
  175.                     stdin=null, stdout=logfile, stderr=logfile,
  176.                     **maybe_drop_privileges)
  177.             elif osextras.find_on_path('xfwm4'):
  178.                 wm = subprocess.Popen('xfwm4',
  179.                     stdin=null, stdout=logfile, stderr=logfile,
  180.                     **maybe_drop_privileges)
  181.             elif osextras.find_on_path('matchbox-window-manager'):
  182.                 wm = subprocess.Popen('matchbox-window-manager',
  183.                     stdin=null, stdout=logfile, stderr=logfile,
  184.                     **maybe_drop_privileges)
  185.             else:
  186.                 raise MissingProgramError, \
  187.                     "No window manager found (tried metacity, xfwm4, matchbox-window-manager)"
  188.  
  189.             if os.path.exists('/usr/lib/gnome-settings-daemon/gnome-settings-daemon'):
  190.                 extras.append(subprocess.Popen(['/usr/lib/gnome-settings-daemon/gnome-settings-daemon'],
  191.                     stdin=null, stdout=logfile, stderr=logfile, **maybe_drop_privileges))
  192.  
  193.             # Accessibility tools
  194.             if accessibility == 'true':
  195.                 fp = open('/proc/cmdline', 'r')
  196.                 if 'access=m2' in fp.readline():
  197.                     if osextras.find_on_path('onboard'):
  198.                         extras.append(subprocess.Popen(['onboard'],
  199.                             stdin=null, stdout=logfile, stderr=logfile))
  200.                 else:
  201.                     if osextras.find_on_path('orca'):
  202.                         time.sleep(15)
  203.                         extras.append(subprocess.Popen(['orca', '-sudo', self.username, '-n'],
  204.                             stdin=null, stdout=logfile, stderr=logfile))
  205.                 fp.close()
  206.         elif self.frontend == 'kde_ui':
  207.             extras.append(subprocess.Popen(['kwriteconfig', '--file', 'kwinrc', '--group', 'Compositing', '--key', 'Enabled', 'false'], stdin=null, stdout=logfile, stderr=logfile, preexec_fn=self.drop_privileges))
  208.             wm = subprocess.Popen('kwin', stdin=null, stdout=logfile,
  209.                 stderr=logfile, preexec_fn=self.drop_privileges)
  210.  
  211.         greeter = subprocess.Popen(program, stdin=null, stdout=logfile, stderr=logfile)
  212.         ret = greeter.wait()
  213.  
  214.         def kill_if_exists(pid, signum):
  215.             try:
  216.                 os.kill(pid, signum)
  217.             except OSError, e:
  218.                 if e.errno != errno.ESRCH:
  219.                     raise
  220.  
  221.         def sigalrm_handler(signum, frame):
  222.             kill_if_exists(wm.pid, signal.SIGKILL)
  223.             for extra in extras:
  224.                 kill_if_exists(extra.pid, signal.SIGKILL)
  225.  
  226.         kill_if_exists(wm.pid, signal.SIGTERM)
  227.         for extra in extras:
  228.             kill_if_exists(extra.pid, signal.SIGTERM)
  229.         if gconfd_running:
  230.             subprocess.call(['gconftool-2', '--shutdown'],
  231.                             stdin=null, stdout=logfile, stderr=logfile,
  232.                             preexec_fn=self.drop_privileges)
  233.         signal.signal(signal.SIGALRM, sigalrm_handler)
  234.         signal.alarm(1) # low patience with WMs failing to exit on demand
  235.         processes = set(extras)
  236.         processes.add(wm)
  237.         while processes:
  238.             done = set()
  239.             for process in processes:
  240.                 try:
  241.                     process.wait()
  242.                     done.add(process)
  243.                 except OSError, e:
  244.                     if e.errno == errno.EINTR:
  245.                         continue
  246.                     raise
  247.             processes -= done
  248.         signal.alarm(0)
  249.         kill_if_exists(server.pid, signal.SIGTERM)
  250.         server.wait()
  251.  
  252.         if ret is not None and ret >= 0:
  253.             return ret
  254.         else:
  255.             return 1
  256.  
  257. if len(sys.argv) < 4:
  258.     sys.stderr.write('Usage: %s <vt[1-N]> <:[0-N]> <username> <program> [<arguments>]\n' % sys.argv[0])
  259.     sys.exit(1)
  260.  
  261. vt, display, username = sys.argv[1:4]
  262. try:
  263.     dm = DM(vt, display, username)
  264. except XStartupError:
  265.     sys.exit(1)
  266. proc = None
  267. if dm.frontend == 'gtk_ui' or dm.frontend == 'mythbuntu_ui':
  268.     proc = ['/etc/init.d/gdm', 'start']
  269. elif dm.frontend == 'kde_ui':
  270.     proc = ['/etc/init.d/kdm', 'start']
  271. ret = dm.run(*sys.argv[4:])
  272. if proc:
  273.     subprocess.Popen(proc)
  274. sys.exit(ret)
  275.